﻿using System;
using System.Collections.Generic;
using System.Linq;

using SBPweb.PROvibe.Shared.Library.Base;

namespace SBPweb.PROvibe.Shared.Library.Components
{

    public static class IModuleExtensions
    {

        #region ContainsId

        public static bool ContainsId(this IEnumerable<IModule> element, int index)
        {
            return element.ContainsId<IModule>(index);
        }

        #endregion

        #region ContainsName

        public static bool ContainsName(this IEnumerable<IModule> element, string name)
        {
            return element.ContainsName<IModule>(name);
        }

        #endregion

        #region ContainsVersion

        public static bool ContainsVersion(this IEnumerable<IModule> element, Version version)
        {
            return element.ContainsVersion<IModule>(version);
        }

        #endregion

        #region ContainsType

        public static bool ContainsType(this IEnumerable<IModule> element, Type type)
        {
            return ContainsType<IModule>(element, type);
        }

        public static bool ContainsType<TType>(this IEnumerable<IModule> element)
           where TType : IModule
        {
            return ContainsType<IModule, TType>(element);
        }

        public static bool ContainsType<TType>(this IEnumerable<IModule> element, Type type)
           where TType : IModule
        {
            return ContainsType<IModule, TType>(element, type);
        }

        public static bool ContainsType<TSource, TType>(this IEnumerable<TSource> element)
            where TSource : IModule
            where TType : TSource
        {
            Type type = typeof(TType);
            return ContainsType<TSource, TType>(element, type);
        }

        public static bool ContainsType<TSource, TType>(this IEnumerable<TSource> element, Type type)
            where TSource : IModule
            where TType : TSource
        {
            return element.Any(x => type.IsAssignableFrom(x.GetType()));
        }

        #endregion


        #region FirstById

        public static IModule FirstById(this IEnumerable<IModule> element, int index)
        {
            return element.FirstById<IModule>(index);
        }

        public static TResult FirstById<TResult>(this IEnumerable<IModule> element, int index)
            where TResult : IModule
        {
            return element.FirstById<IModule, TResult>(index);
        }

        #endregion

        #region FirstByName

        public static IModule FirstByName(this IEnumerable<IModule> element, string name)
        {
            return element.FirstByName<IModule>(name);
        }

        public static TResult FirstByName<TResult>(this IEnumerable<IModule> element, string name)
            where TResult : IModule
        {
            return element.FirstByName<IModule, TResult>(name);
        }

        #endregion

        #region FirstByVersion

        public static IModule FirstByVersion(this IEnumerable<IModule> element, Version version)
        {
            return element.FirstByVersion<IModule>(version);
        }

        public static TResult FirstByVersion<TResult>(this IEnumerable<IModule> element, Version version)
            where TResult : IModule
        {
            return element.FirstByVersion<IModule, TResult>(version);
        }

        #endregion

        #region FirstByType

        public static IModule FirstByType(this IEnumerable<IModule> element, Type type)
        {
            return FirstByType<IModule>(element, type);
        }

        public static TResult FirstByType<TResult>(this IEnumerable<IModule> element)
            where TResult : IModule
        {
            return FirstByType<IModule, TResult>(element);
        }

        public static TResult FirstByType<TResult>(this IEnumerable<IModule> element, Type type)
            where TResult : IModule
        {
            return FirstByType<IModule, TResult>(element, type);
        }

        public static TResult FirstByType<TSource, TResult>(this IEnumerable<TSource> element)
            where TSource : IModule
            where TResult : TSource
        {
            Type type = typeof(TResult);
            return FirstByType<TSource, TResult>(element, type);
        }

        public static TResult FirstByType<TSource, TResult>(this IEnumerable<TSource> element, Type type)
            where TSource : IModule
            where TResult : TSource
        {
            return (TResult)element.FirstOrDefault(x => type.IsAssignableFrom(x.GetType()));
        }

        #endregion


        #region WhereIdIs

        public static IEnumerable<IModule> WhereIdIs(this IEnumerable<IModule> element, int index)
        {
            return element.WhereIdIs<IModule>(index);
        }

        public static IEnumerable<TResult> WhereIdIs<TResult>(this IEnumerable<IModule> element, int index)
            where TResult : IModule
        {
            return element.WhereIdIs<IModule, TResult>(index);
        }

        #endregion

        #region WhereNameIs

        public static IEnumerable<IModule> WhereNameIs(this IEnumerable<IModule> element, string name)
        {
            return element.WhereNameIs<IModule>(name);
        }

        public static IEnumerable<TResult> WhereNameIs<TResult>(this IEnumerable<IModule> element, string name)
            where TResult : IModule
        {
            return element.WhereNameIs<IModule, TResult>(name);
        }

        #endregion

        #region WhereVersionIs

        public static IEnumerable<IModule> WhereVersionIs(this IEnumerable<IModule> element, Version version)
        {
            return element.WhereVersionIs<IModule>(version);
        }

        public static IEnumerable<TResult> WhereVersionIs<TResult>(this IEnumerable<IModule> element, Version version)
            where TResult : IModule
        {
            return element.WhereVersionIs<IModule, TResult>(version);
        }

        #endregion

        #region WhereTypeIs

        public static IEnumerable<IModule> WhereTypeIs(this IEnumerable<IModule> element, Type type)
        {
            return WhereTypeIs<IModule>(element, type);
        }

        public static IEnumerable<TResult> WhereTypeIs<TResult>(this IEnumerable<IModule> element)
            where TResult : IModule
        {
            return WhereTypeIs<IModule, TResult>(element);
        }

        public static IEnumerable<TResult> WhereTypeIs<TResult>(this IEnumerable<IModule> element, Type type)
            where TResult : IModule
        {
            return WhereTypeIs<IModule, TResult>(element, type);
        }

        public static IEnumerable<TResult> WhereTypeIs<TSource, TResult>(this IEnumerable<TSource> element)
            where TSource : IModule
            where TResult : TSource
        {
            Type type = typeof(TResult);
            return WhereTypeIs<TSource, TResult>(element, type);
        }

        public static IEnumerable<TResult> WhereTypeIs<TSource, TResult>(this IEnumerable<TSource> element, Type type)
            where TSource : IModule
            where TResult : TSource
        {
            return element.Where(x => type.IsAssignableFrom(x.GetType())).Cast<TResult>().ToList();
        }

        #endregion

    }

}